package api

import (
	"cgs-server/helper"
	"cgs-server/server"
	"cgs-server/server/base"
	"cgs-server/server/cgs/app/models"
	"cgs-server/server/cgs/app/service"
	"cgs-server/server/cgs/app/store"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"net/http"
	"net/url"
)

type WorksheetInfoHandler struct {
	// srv service
	srv service.Service
	// store
	store store.Factory
}

func NewWorksheetInfoHandler(store store.Factory) *WorksheetInfoHandler {
	return &WorksheetInfoHandler{
		srv:   service.NewService(store),
		store: store,
	}
}

func (wg *WorksheetInfoHandler) Get(w http.ResponseWriter, r *http.Request) {
	groupId := r.FormValue("id")
	if groupId == "" {
		_, _ = helper.WriteJSON(w, server.Fail("worksheet id is required"))
		return
	}
	user, err := base.GetCurrentUser(r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	ws, err := wg.srv.WorksheetInfo().Get(groupId, user)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	_, _ = helper.WriteJSON(w, server.OK().WithData(ws))
}

func (wg *WorksheetInfoHandler) Save(w http.ResponseWriter, r *http.Request) {
	var wsInfo models.WorksheetInfo
	err := helper.ReadRequestBody(&wsInfo, w, r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	if wsInfo.Type == nil {
		_, _ = helper.WriteJSON(w, server.Fail("worksheet type is required"))
		return
	}

	user, err := base.GetCurrentUser(r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	err = wg.srv.WorksheetInfo().Save(&wsInfo, user)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	_, _ = helper.WriteJSON(w, server.OK().WithData(bson.M{"id": wsInfo.GetId()}))
}

func (wg *WorksheetInfoHandler) Delete(w http.ResponseWriter, r *http.Request) {
	groupId := r.FormValue("id")
	if groupId == "" {
		_, _ = helper.WriteJSON(w, server.Fail("worksheet id is required"))
		return
	}
	user, err := base.GetCurrentUser(r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	err = wg.srv.WorksheetInfo().Delete(groupId, user)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	_, _ = helper.WriteJSON(w, server.OK())
}

func (wg *WorksheetInfoHandler) Update(w http.ResponseWriter, r *http.Request) {
	var wsInfo models.WorksheetInfo
	err := helper.ReadRequestBody(&wsInfo, w, r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	if wsInfo.Type == nil {
		_, _ = helper.WriteJSON(w, server.Fail("worksheet type is required"))
		return
	}
	user, err := base.GetCurrentUser(r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	err = wg.srv.WorksheetInfo().Update(&wsInfo, user)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	_, _ = helper.WriteJSON(w, server.OK())
}

func (wg *WorksheetInfoHandler) ListByAppId(w http.ResponseWriter, r *http.Request) {
	appId := r.FormValue("appId")
	wsTypes := r.Form["type"]
	simplify := r.FormValue("simplify") == "true"
	if appId == "" {
		_, _ = helper.WriteJSON(w, server.Fail("appId is required"))
		return
	}
	user, err := base.GetCurrentUser(r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	ws, err := wg.srv.WorksheetInfo().ListByAppId(appId, wsTypes, user)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}

	if simplify {
		for _, info := range *ws {
			info.Config = nil
			info.ViewList = nil
		}
	}

	_, _ = helper.WriteJSON(w, server.OK().WithData(ws))
}

func (wg *WorksheetInfoHandler) UploadExcel(w http.ResponseWriter, r *http.Request) {
	_ = r.ParseMultipartForm(server.Config.Upload.MaxSize)
	files := r.MultipartForm.File
	if len(files) == 0 {
		_, _ = helper.WriteJSON(w, server.Fail("please select an file"))
		return
	}
	excel, err := wg.srv.WorksheetInfo().UploadExcel(files["file"][0])
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	_, _ = helper.WriteJSON(w, server.OK().WithData(excel))
}

func (wg *WorksheetInfoHandler) PreviewExcel(w http.ResponseWriter, r *http.Request) {
	filePath := r.FormValue("filePath")
	if filePath == "" {
		_, _ = helper.WriteJSON(w, server.Fail("filePath is required"))
		return
	}
	excel, err := wg.srv.WorksheetInfo().PreviewExcel(filePath)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	_, _ = helper.WriteJSON(w, server.OK().WithData(excel))
}

func (wg *WorksheetInfoHandler) ImportExcel(w http.ResponseWriter, r *http.Request) {
	var ex models.ExcelImport
	err := helper.ReadRequestBody(&ex, w, r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	user, err := base.GetCurrentUser(r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	err = wg.srv.WorksheetInfo().ImportExcel(&ex, user)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	_, _ = helper.WriteJSON(w, server.OK().WithData(bson.M{
		"fieldsData": ex.RowList,
		"errorData":  ex.Errors,
	}))
}

// ExportExcel 导出表单数据到 excel
func (wg *WorksheetInfoHandler) ExportExcel(w http.ResponseWriter, r *http.Request) {
	var filterParam models.FilterParam
	err := helper.ReadRequestBody(&filterParam, w, r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	err = helper.GetValidator().Struct(&filterParam)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	user, err := base.GetCurrentUser(r)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}

	excel, name, err := wg.srv.WorksheetInfo().ExportExcel(&filterParam, user)
	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	head := w.Header()
	head.Set("content-type", "application/octet-stream")
	head.Set("Content-Disposition", fmt.Sprintf("attachment;filename=%s.xlsx", url.QueryEscape(name)))
	_ = excel.Write(w)
}
